package com.wiseman.writing.utility.database;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


abstract public class WDatabase{

	//keys
	public static final int DB_VER = 1;

	private static final String KEY_ID = "_id";
	private static final String KEY_DATE = "_date";
	
	public static final String DATE_FORMAT = "yyyy-MM-dd";
			
	//fields.
	private DatabaseHelper mDatabaseHelper = null;
	private SQLiteDatabase mSQLiteDatabase = null;
	private Context mContext = null;
	private String mCreateSql;
	private String mTableName;
	
	private final String CREATESQL_START = "CREATE TABLE" ;	
	private final String CREATESQL_END = ")";
	 
	protected HashMap<String, String> mKeyMap  = new HashMap<String, String>();
	public abstract void fillKeys();	
	
	static  public abstract class DbData{
		
		public Date mDate;
		
		public DbData() {
			mDate = new Date();
		}

		public ContentValues makeContentValue() {
			ContentValues initVal = new ContentValues();

			initVal.put(KEY_DATE, toDateString());
			
			fillOtherData(initVal);			
			return initVal;			
		}		
		
		public void getData(Cursor c){
		
			String strDate = c.getString(c.getColumnIndex(KEY_DATE));
			parseDate(strDate);			
			
			getOtherData(c);	
		}
		
		public abstract void fillOtherData(ContentValues initVal); 	
		public abstract void getOtherData(Cursor c); 	

		public String toDateString() {
			DateFormat sdf = new SimpleDateFormat(DATE_FORMAT, Locale.US);
			return sdf.format(mDate);
		}

		public void parseDate(String datestr) {
			DateFormat sdf = new SimpleDateFormat(DATE_FORMAT, Locale.US);
			try {
				mDate = sdf.parse(datestr);
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	class DatabaseHelper extends SQLiteOpenHelper {
		public DatabaseHelper(Context context) {			
			super(context, context.getPackageName(), null, DB_VER);			
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(mCreateSql);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
		}
	}	


	public WDatabase(Context context, String tableName) {
		
		mCreateSql = CREATESQL_START;
		mCreateSql += " " +	tableName;
		mCreateSql += " ( " + KEY_ID   + " " + "INTEGER" + " " + "PRIMARY KEY";
		mCreateSql += " , " + KEY_DATE + " " + "TEXT";
			
		fillKeys();
		Set<String> keys = mKeyMap.keySet();
		for(String s:keys){
			mCreateSql += " , " + s + " " + mKeyMap.get(s);		
		}
		
		mCreateSql += CREATESQL_END;
		
		mContext = context;
		mTableName = tableName;
	}

	public void open() throws SQLException {
		mDatabaseHelper = new DatabaseHelper(mContext);
		mSQLiteDatabase = mDatabaseHelper.getWritableDatabase();		
	}

	public void close() {
		mDatabaseHelper.close();
	}

	public long insertData(DbData data) {
		return mSQLiteDatabase.insert(mTableName, null, data.makeContentValue());
	}

	public boolean deleteData(DbData data) {
		return mSQLiteDatabase.delete(mTableName, KEY_DATE  + "= ?", new String[]{data.toDateString()}) > 0;
	}
	
	public Cursor fetchAllData() {
		return mSQLiteDatabase.query(mTableName, null, null, null, null, null, null);
	}
	
	public void getDataById(long rowid, DbData data) {
	
		Cursor c = mSQLiteDatabase.query(mTableName, null, KEY_ID + "=" + rowid, null, null, null, KEY_DATE + " desc");

		if (c.moveToNext()) {
			data.getData(c);			
		}

		c.close();		
	}
	
	public boolean getDataByDate(DbData data) {
		
		boolean hasData = false;
		
		Cursor c = mSQLiteDatabase.query(mTableName, null,  KEY_DATE  + "= ?", new String[]{data.toDateString()}, null, null, null);

		if (c.moveToNext()) {
			data.getData(c);
			hasData = true;
		}

		c.close();	
		
		return hasData;
	}
	
	public boolean updateData(DbData data) {
			
		return mSQLiteDatabase.update(mTableName, data.makeContentValue(), KEY_DATE  + "= ?", new String[]{data.toDateString()}) > 0;
	}		

}
